(PYTHON) Day - 15 Itertools(2)

Reference

  • 문제 출처 - HackerRank
  • 파이썬 연습 - Practice - Python

개인적인 생각과 상상으로 작성한 내용들이 포함되어 있습니다
문제를 풀고 Discussion Tab을 참고하며 코드 스타일을 개선하려고 노력하고자 합니다


HackerRank


Itertools


itertools.product()


문제 : A, B의 곱집합을 구하는 문제
입력 : A의 원소들; B의 원소들;
출력 : product(A, B)


> > > # Sample code
> > >
> > > from itertools import product
> > >
> > > print list(product([1,2,3],repeat = 2))
> > > [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
> > >
> > > print list(product([1,2,3],[3,4]))
> > > [(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]
> > >
> > > A = [[1,2,3],[3,4,5]]
> > > print list(product(\*A))
> > > [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]
> > >
> > > B = [[1,2,3],[3,4,5],[7,8]]
> > > print list(product(\*B))
> > > [(1, 3, 7), (1, 3, 8), (1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 3, 7), (2, 3, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8), (3, 3, 7), (3, 3, 8), (3, 4, 7), (3, 4, 8), (3, 5, 7), (3, 5, 8)]
> > >

1 2
3 4

(1, 3) (1, 4) (2, 3) (2, 4)

from itertools import product

A = [int(a) for a in input().split()]
B = [int(b) for b in input().split()]

print(\*product(A, B))

itertools.permutations()


문제 : 문자열 S가 주어졌을 때 k의 크기로 뽑을 수 있는 순열(permutation)을 사전순(lexicographic order)으로 출력하는 문제
입력 : S, k; (문자열은 모두 대문자)
출력 : S로 만들 수 있는 순열을 한줄씩 출력


> > > # Sample code
> > >
> > > from itertools import permutations
> > > print permutations(['1','2','3'])
> > > <itertools.permutations object at 0x02A45210>
> > >
> > > print list(permutations(['1','2','3']))
> > > [('1', '2', '3'), ('1', '3', '2'), ('2', '1', '3'), ('2', '3', '1'), ('3', '1', '2'), ('3', '2', '1')]
> > >
> > > print list(permutations(['1','2','3'],2))
> > > [('1', '2'), ('1', '3'), ('2', '1'), ('2', '3'), ('3', '1'), ('3', '2')]
> > >
> > > print list(permutations('abc',3))
> > > [('a', 'b', 'c'), ('a', 'c', 'b'), ('b', 'a', 'c'), ('b', 'c', 'a'), ('c', 'a', 'b'), ('c', 'b', 'a')]
> > >

HACK 2

AC
AH
AK
CA
CH
CK
HA
HC
HK
KA
KC
KH

from itertools import permutations

S, k = input().split()
print(\*[''.join(p) for p in permutations(sorted(S), int(k))], sep='\n')

itertools.combinations()


문제 : 문자열 S가 주어졌을 때 k의 크기로 뽑을 수 있는 조합(combination)을 사전순으로 출력하는 문제
입력 : S, k; (문자열은 모두 대문자)
출력 : S로 만들 수 있는 서로 다른 조합을 한줄씩 출력


> > > # Sample code
> > >
> > > from itertools import combinations
> > >
> > > print list(combinations('12345',2))
> > > [('1', '2'), ('1', '3'), ('1', '4'), ('1', '5'), ('2', '3'), ('2', '4'), ('2', '5'), ('3', '4'), ('3', '5'), ('4', '5')]
> > >
> > > A = [1,1,3,3,3]
> > > print list(combinations(A,4))
> > > [(1, 1, 3, 3), (1, 1, 3, 3), (1, 1, 3, 3), (1, 3, 3, 3), (1, 3, 3, 3)]
> > >

HACK 2

A
C
H
K
AC
AH
AK
CH
CK
HK

from itertools import combinations

S, k = input().split()
print(\*[''.join(c) for i in range(1, int(k)+1) for c in combinations(sorted(S), i)], sep='\n')

itertools.combinations_with_replacement()


문제 : 문자열 S가 주어졌을 때 k의 크기로 뽑을 수 있는 중복조합(combinations with replacement)을 사전순으로 출력하는 문제
입력 : S, k; (문자열은 모두 대문자)
출력 : S로 만들 수 있는 중복조합을 한줄씩 출력


> > > # Sample code
> > >
> > > from itertools import combinations_with_replacement
> > >
> > > print list(combinations_with_replacement('12345',2))
> > > [('1', '1'), ('1', '2'), ('1', '3'), ('1', '4'), ('1', '5'), ('2', '2'), ('2', '3'), ('2', '4'), ('2', '5'), ('3', '3'), ('3', '4'), ('3', '5'), ('4', '4'), ('4', '5'), ('5', '5')]
> > >
> > > A = [1,1,3,3,3]
> > > print list(combinations(A,2))
> > > [(1, 1), (1, 3), (1, 3), (1, 3), (1, 3), (1, 3), (1, 3), (3, 3), (3, 3), (3, 3)]
> > >

HACK 2

AA
AC
AH
AK
CC
CH
CK
HH
HK
KK

from itertools import combinations_with_replacement

S, k = input().split()

print(\*[''.join(c)for c in combinations_with_replacement(sorted(S), int(k))], sep='\n')

Compress the String!


문제 : 문자열 S가 주어졌을 때 같은 문자끼리 그룹으로 묶어서 압축된 표현을 출력하는 문제
입력 : 문자열 S (숫자 0에서 9까지로 구성됨)
출력 : 문자를 c로 연속으로 출현한 횟수를 X라고 했을 때 (X, c)로 표현

1222311

(1, 1) (3, 2) (1, 3) (2, 1)

파이썬의 goupby() 함수는 SQL의 개념과 조금 달라서 주의해야겠다.
만약 SQL의 그룹방식을 구현하고 싶다면 함수를 사용하기 전 정렬을 시켜주면 된다.

from itertools import groupby

S = input()
print(\*[(len(list(grp)), int(key)) for key, grp in groupby(S)])

Iterables and Iterators


문제 : N개의 영문자 중에서 K개로 만들 수 있는 조합들 중에 ‘a’를 포함하는 조합을 확률로 출력하는 문제
입력 : 문자수 N; (N개의) 문자들; 조합 크기 K;
출력 : 확률을 소수점 3번째 자리까지 표현

4
a a c d
2

0.8333

combinations() 함수를 사용하여 전체 경우의 수를 구하고 문자 ‘a’가 있는 조합의 수를 구함
list()[]의 차이점을 주의 - difference btw list() and []

import itertools as it

N, letters, K = input(), input().split(), int(input())

c_letters = list(it.combinations(letters, K))
contain = [c for c in c_letters if 'a' in c]

print('{:.4f}'.format(len(contain)/len(c_letters)))

math 모듈을 사용해서 직접 수학적인 계산을 사용한 경우도 있음

from math import factorial

def C(n, k):
if n < k:
return 0
return factorial(n) // factorial(n-k)

N = int(input())
n_a = input().split().count('a')
K = int(input())

print('%.4f' % (1 - C(N - n_a, K) / C(N, K)))

수행시간을 비교해보면 그 차이가 매우 사소하기 때문에 combinations() 함수를 사용하는게 직관적으로 보기 좋은 것 같음

import itertools as it
from math import factorial
from timeit import timeit

def C(n, k):
if n < k:
return 0
return factorial(n) // factorial(n-k)

N, letters, K = int(input()), input().split(), int(input())

n_a = letters.count('a')

c_letters = list(it.combinations(letters, K))
contain = [c for c in c_letters if 'a' in c]

print(timeit('{:.4f}'.format(len(contain)/len(c_letters)))) # 0.01438812300000003
print(timeit('{:.4f}'.format(1 - C(N - n_a, K) / C(N, K)))) # 0.011570051000000081

Maximize It!


문제 : f(x) = x^2 이고, S = (f(x1) + f(x2) + …) % M 일 때, 가장 큰 S를 구하는 문제
입력 : K, M; (K번 반복) 리스트의 크기, 숫자들…;
출력(예제) : 각 리스트에서 5, 9, 10을 뽑은 경우 (5^2 + 9^2 + 10^2)%1000 = 206으로 가장 크다

3 1000
2 5 4
3 7 8 9
5 5 7 8 9 10

206

처음에 문제를 잘못 이해하고 각 리스트에서 가장 큰 수를 뽑아서 S를 구하는 문제인줄 알았다…

K, M = map(int, input().split())
N = [[int(num) for num in input().split()[1:]] for \_ in range(K)]
max_N = list(map(lambda x: max(x)\*\*2, N))

print(sum(max_N) % M)

각 리스트를 곱하여(product) 모든 조합을 만들고, 람다식을 이용해 각 조합의 S를 계산하여 최대값을 구한다.

from itertools import product

K, M = map(int, input().split())
N = [[int(num) for num in input().split()[1:]] for \_ in range(K)]
max_S = max(list(map(lambda x: sum(i\**2 for i in x) % M, product(*N))))

print(max_S)